package com.uxsino.simo.collector.connections;

import java.util.Map;
import java.util.Properties;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.uxsino.simo.connections.AbstractConnection;
import com.uxsino.simo.connections.IFileConnection;
import com.uxsino.simo.connections.exception.SimoQueryException;
import com.uxsino.simo.connections.target.TCPTarget;

public abstract class AbstractSFTPConnection<T extends TCPTarget> extends AbstractConnection<TCPTarget>
    implements IFileConnection<TCPTarget> {

    private static Logger logger = LoggerFactory.getLogger(AbstractSFTPConnection.class);

    private static TcpSessionManager sessionManager = new TcpSessionManager();

    protected JSch jsch;

    protected Properties config;

    protected Session session;

    protected ChannelSftp channelSftp;

    protected final static int CONN_TIME_OUT = 50000;

    protected final static int SESSION_TIME_OUT = 900000;

    public AbstractSFTPConnection() {
        jsch = new JSch();
        config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        config.put("PreferredAuthentications", "password,keyboard-interactive,publickey,gssapi-with-mic");
    }

    @Override
    public int connect(TCPTarget target) {
        super.connect(target);
        connected = false;
        state = 0;
        sessionManager.waitFor(target.host, target.port);
        try {
            session = jsch.getSession(target.getUsername(), target.host, target.port);
            session.setPassword(target.getPassword());
            session.setConfig(config);
            session.setTimeout(SESSION_TIME_OUT);
            session.connect(CONN_TIME_OUT);
            if (!session.isConnected()) {
                return state;
            }
            connectForFileTrans(target);
        } catch (JSchException e) {
            logger.error("error getting connection", e);
        }
        state = 1;
        return state;
    }

    @Override
    public Object buildCmd(String cmdPattern, Map<String, String> args) throws SimoQueryException {
        return cmdPattern;
    }

    @Override
    public int close() {
        try {
        if (channelSftp != null) {
            channelSftp.disconnect();
        }
        }catch (Exception e){
            logger.error("close sftp channel error: ", e);
        }
        try {
        if (session != null) {
            session.disconnect();
        }
        }catch (Exception e){
            logger.error("close sftp session error: ", e);
        }
        connected = false;

        super.close();
        return 0;
    }

    @Override
    public void connectForFileTrans(TCPTarget target) {
        try {
            channelSftp = (ChannelSftp) session.openChannel("sftp");
            channelSftp.connect();
            connected = true;
        } catch (JSchException e) {
            logger.error("error connecting for file transfer", e);
            connected = false;
        }
    }

}